package com.hejia.alauda.entity;

import static com.hejia.alauda.utils.DateTimeUtil.getMinDate;
import static com.hejia.alauda.utils.RateUtil.calculateDate;
import static com.hejia.alauda.utils.Utils.formatDate;
import static org.apache.commons.lang3.StringUtils.trimToEmpty;
import static org.apache.commons.lang3.time.DateUtils.addDays;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import javax.persistence.Column;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.codehaus.jackson.annotate.JsonIgnore;

import com.fasterxml.jackson.annotation.JsonView;
import com.hejia.alauda.entity.Product.Status;
import com.hejia.alauda.entity.example.RedemptionRequestExample;
import com.hejia.alauda.persistence.mybatis.FinancingIncomeRuleMapper;
import com.hejia.alauda.persistence.mybatis.RedemptionRequestMapper;
import com.hejia.alauda.service.CommonServiceImpl;
import com.hejia.alauda.utils.DateTimeUtil;
import com.hejia.alauda.utils.InterestUtils;
/**
 * 金融包,购买产品后产生
 * Created by Johnny(johnny@hejiajinrong.com) on 14-9-2.
 */
public class Financing extends BaseEntity{
	
	protected static final Log logger = LogFactory.getLog(Financing.class);

	/**
	 * 
	 */
	private static final long serialVersionUID = -6953798993257484997L;

	/**
	 * 金融包状态
	 * @author paul
	 * STATUS_DEFAULT-未到起息日
	 * STATUS_INTEREST-计算利息中
	 * STATUS_EXPIRED-已经到期
	 * STATUS_PAYAPPLY-还款申请中
	 * STATUS_PAYBACK-已经还款（待确认）
	 * STATUS_REPAID-已经还款（已确认）
	 */
	public static enum Status {
		STATUS_DEFAULT, STATUS_INTEREST, STATUS_EXPIRED,STATUS_PAYAPPLY, STATUS_PAYBACK, STATUS_REPAID;
	}
	
	public interface ListView{};
	public interface DetailView{};
	
    @Column
    @JsonIgnore
    @JsonView({DetailView.class,ListView.class})
    private Product product;

    @Column
    @JsonView({ListView.class, DetailView.class})
    private String name; //名称

    @Column
    private Integer term; //期限(天为单位)
    
    @Column
    private Integer minTerm; //保底期限(天为单位)
    
    @Column
    private Integer occupiedDays; //实际占用天数

    @Column
    private BigDecimal interestRate; //年化利率

    @Column
    @JsonView({ListView.class, DetailView.class})
    private Date valueDate;  //起息日
    
    @Column
	@JsonView({ListView.class, DetailView.class})
    private Date balanceDate;  //结息日(最后一天利息)
    
    @Column
    @JsonView({ListView.class, DetailView.class})
    private Date settlementDate; //到期日

    @Column
    @JsonView({ListView.class, DetailView.class})
    private BigDecimal amount; //购买金额
   
    @Column
    private User user;
    
    @Column
    @JsonView({ListView.class, DetailView.class})
    private BigDecimal income;//当前收益
    
    @Column
    @JsonView({ListView.class, DetailView.class})
    private Status status;//状态 标记是否到期 是否回款等
    
    @Column
    @JsonView(DetailView.class)
    private Order order;//订单
    
	@Column
    @JsonView({ListView.class, DetailView.class})
	private Date repaymentTime;// 偿还时间

	@Column
	private String payGateCode;//支付网关代码
	
	@Column
    private String agreementNumber; // 资产转让协议编号资产部分
	
	private Integer remains;
	
	@Column
	@JsonView({ListView.class})
	private RepaymentOrder repaymentOrder;
	
	@Column
	private String track;
	
	@JsonView({ListView.class, DetailView.class})
	public Integer getRemainDays(){
		
		int days = DateTimeUtil.getDaysBetween(new Date(), settlementDate).intValue();
		
		return  days>0?days:0;
		
	}
	
    @JsonView({ListView.class, DetailView.class})
	public BigDecimal getMinIncome(){
		return InterestUtils.calculateInterest(this.getAmount(), this.getInterestRate(), this.getMinTerm());
	}
	
    public Integer getRemains() {
    	if(remains == null)
    		remains = this.getRemainDays();
		return remains;
	}

	public void setRemains(Integer remains) {
		this.remains = remains;
	}

	public Product getProduct() {
        return product;
    }

    public void setProduct(Product product) {
        this.product = product;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getTerm() {
        return term;
    }

    public void setTerm(Integer term) {
        this.term = term;
    }

    public BigDecimal getInterestRate() {
    	return interestRate;
    }

    public void setInterestRate(BigDecimal interestRate) {
        this.interestRate = interestRate;
    }

    public Date getValueDate() {
        return valueDate;
    }

    public void setValueDate(Date valueDate) {
        this.valueDate = valueDate;
    }

    public BigDecimal getAmount() {
        return amount == null?new BigDecimal(0):amount;
    }

    public void setAmount(BigDecimal amount) {
        this.amount = amount;
    }

	public User getUser() {
		return user;
	}

	public void setUser(User user) {
		this.user = user;
	}

	public Status getStatus() {
		
		//如果是待计息状态 且 满标起息 且满标 则返回计息中
		if(Status.STATUS_DEFAULT.equals(status)
				&& product.isCompletedValue() 
				&& Product.Status.SOLDOUT.toString().equals(product.getFinalStatus()))
			return Status.STATUS_INTEREST;
		
		return status;
	}

	public void setStatus(Status status) {
		this.status = status;
	}

	public Date getBalanceDate() {
		
		if(balanceDate == null && getRepaymentTime() != null)
			
			balanceDate = DateTimeUtil.addDate(getRepaymentTime(), -1);
			
		return balanceDate;
	}

	public void setBalanceDate(Date balanceDate) {
		this.balanceDate = balanceDate;
	}

	public Date getSettlementDate() {
		return settlementDate;
	}

	public void setSettlementDate(Date settlementDate) {
		this.settlementDate = settlementDate;
	}

	public BigDecimal getIncome() {
		return income;
	}

	public void setIncome(BigDecimal income) {
		this.income = income;
	}

	public Order getOrder() {
		return order;
	}

	public void setOrder(Order order) {
		this.order = order;
	}
	
	public Date getExpiredDate(){
		return addDays(getSettlementDate(),-1);
	}
	
	public String getStatusStr() {
		String statusStr = "未知状态";
		
		int interval = calculateDate(new Date(), getExpiredDate());
		if(getStatus() != null){
			switch (getStatus()) {
			case STATUS_REPAID:
				statusStr = "已还款";
				break;
			case STATUS_PAYBACK:
				statusStr = "还款中";
				break;
			case STATUS_EXPIRED:
				statusStr = "兑付中";
				break;
			case STATUS_DEFAULT:
			case STATUS_INTEREST:
			case STATUS_PAYAPPLY:
				FinancingIncomeRule rule = getFinancingIncomeRule();
				if(rule == null){
					statusStr = interval>=0 ? (interval>0 ? (interval + "天后到期") : "今日到期") : "兑付中";
				} else {
					statusStr = interval>=0 ? (isRedeemed() ?  "已赎回" : (isRedemption() ? "可赎回" : "收益中")) : "兑付中";
				}
				break;
			default:
				break;
			}
		}
//		if(CommonServiceImpl.devMode){
//			int interval = calculateDate(new Date(), getExpiredDate());
//			if(getStatus() != null){
//				switch (getStatus()) {
//				case STATUS_REPAID:
//					statusStr = "已还款";
//					break;
//				case STATUS_PAYBACK:
//					statusStr = "还款中";
//					break;
//				case STATUS_EXPIRED:
//					statusStr = "兑付中";
//					break;
//				case STATUS_DEFAULT:
//				case STATUS_INTEREST:
//				case STATUS_PAYAPPLY:
//					FinancingIncomeRule rule = getFinancingIncomeRule();
//					if(rule == null){
//						statusStr = interval>=0 ? (interval>0 ? (interval + "天后到期") : "今日到期") : "兑付中";
//					} else {
//						statusStr = interval>=0 ? (isRedeemed() ?  "已赎回" : (isRedemption() ? "可赎回" : "收益中")) : "兑付中";
//					}
//					break;
//				default:
//					break;
//				}
//			}
//		} else {
//			int interval = calculateDate(new Date(), getExpiredDate());
//			if(getStatus() != null){
//				switch (getStatus()) {
//				case STATUS_REPAID:
//				case STATUS_PAYBACK:
//					statusStr = "已兑付";
//					break;
//				case STATUS_EXPIRED:
//					statusStr = "兑付中";
//					break;
//				case STATUS_DEFAULT:
//				case STATUS_INTEREST:
//				case STATUS_PAYAPPLY:
//					FinancingIncomeRule rule = getFinancingIncomeRule();
//					if(rule == null){
//						statusStr = interval>=0 ? (interval>0 ? (interval + "天后到期") : "今日到期") : "兑付中";
//					} else {
//						statusStr = interval>=0 ? (isRedeemed() ?  "已赎回" : (isRedemption() ? "可赎回" : "收益中")) : "兑付中";
//					}
//					break;
//				default:
//					break;
//				}
//			}
//		}
		return statusStr;
	}
	
	public static String getStatusStr(Date expiredDate, Status status) { 
		int interval = calculateDate(new Date(), expiredDate);
//		if(Status.STATUS_PAYBACK.equals(status)||Status.STATUS_REPAID.equals(status)){
//			return "已兑付";
//		} else if(Status.STATUS_EXPIRED.equals(status)||Status.STATUS_PAYAPPLY.equals(status)){
//			return "兑付中";
//		} else if(Status.STATUS_DEFAULT.equals(status)||Status.STATUS_INTEREST.equals(status)){
//			return interval>=0 ? (interval>0 ? (interval + "天后到期") : "今日到期") : "兑付中";
//		} else {
//			return "未知状态";
//		}
		String statusStr = "未知状态";
		if(status != null){
			switch (status) {
			case STATUS_REPAID:
			case STATUS_PAYBACK:
				statusStr = "已兑付";
				break;
			case STATUS_EXPIRED:
				statusStr = "兑付中";
				break;
			case STATUS_DEFAULT:
			case STATUS_INTEREST:
			case STATUS_PAYAPPLY:
				statusStr = interval>=0 ? (interval>0 ? (interval + "天后到期") : "今日到期") : "兑付中";
				break;
			default:
				break;
			}
		}
		return statusStr;
	}

	public Date getRepaymentTime() {
		return repaymentTime;
	}

	public void setRepaymentTime(Date repaymentTime) {
		this.repaymentTime = repaymentTime;
	}

	public String getPayGateCode() {
		return payGateCode;
	}

	public void setPayGateCode(String payGateCode) {
		this.payGateCode = payGateCode;
	}
	
	public String getAgreementNumber() {
		return agreementNumber;
	}

	public void setAgreementNumber(String agreementNumber) {
		this.agreementNumber = agreementNumber;
	}
	
	/**
	 * 获取完整资产协议编号
	 * @return	完整资产协议编号
	 */
	public String getFullAgreementNumber(){
		if(this.getProduct() == null ||
		   this.getProduct().getAgreementNumber() == null ||
		   this.getAgreementNumber() == null){
			return "";
		}
		return this.getProduct().getAgreementNumber() + this.getAgreementNumber();
	}
	
	public BigDecimal getStageInterestRate() {
		FinancingIncomeRule rule = getFinancingIncomeRule();
		return rule == null ? getInterestRate() : rule.getInterestRate();
	}
	
	

    public RepaymentOrder getRepaymentOrder() {
		return repaymentOrder;
	}

	public void setRepaymentOrder(RepaymentOrder repaymentOrder) {
		this.repaymentOrder = repaymentOrder;
	}

	@Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (obj == this){
            return true;
        }
        if (getClass() != obj.getClass()){
            return false;
        }
        Financing financing = (Financing)obj;
        return (this.getId() == financing.getId());
    }

    @Override
    public int hashCode() {
        final int PRIME = 31;
        long result = 1;
        result = PRIME * result + getId();
        return (int)result;
    }
    
    public String getColor() {
    	String statusStr = trimToEmpty(getStatusStr());
    	if("已兑付".equals(statusStr) || "还款中".equals(statusStr) || "已还款".equals(statusStr)){
			return "32CD32";
		} else if("兑付中".equals(statusStr)){
			return "E08002";
		} else {
			return "FF0000";
		}
    }
    
//	public ProductEarningsRule getCurrentRule() {
//		if (getProduct() != null && getProduct().getCategory() != null) {
//			switch (getProduct().getCategory()) {
//			case CURRENT:
//				if (!isEmpty(getProduct().getEarningsRules())) {
//					Calendar calendar = Calendar.getInstance();
//					String dateStr = formatDate(getMinDate(calendar.getTime(), getExpiredDate()));
//					for(int i=0;i<getProduct().getEarningsRules().size();i++){
//						if (dateStr.compareTo(formatDate(getProduct().getEarningsRules().get(i).getDueDate())) <= 0) {
//							getProduct().getEarningsRules().get(i).setStage(i + 1);
//							getProduct().getEarningsRules().get(i).setLast(i == getProduct().getEarningsRules().size()-1);
//							return getProduct().getEarningsRules().get(i);
//						}
//					}
//				}
//				break;
//			default:
//				break;
//			}
//		}
//		return null;
//	}
	
	public List<FinancingIncomeRule> getFinancingIncomeRules() {
		//MongoTemplate mongoTemplate = CommonServiceImpl.applicationContext.getBean(MongoTemplate.class);
		FinancingIncomeRuleMapper financingIncomeRuleMapper = CommonServiceImpl.applicationContext.getBean(FinancingIncomeRuleMapper.class);
		return financingIncomeRuleMapper.findFinancingIncomeRulesByFinancing(getId());
	}
	
	public FinancingIncomeRule getFinancingIncomeRule() {
		if (getProduct() != null){
			switch (getProduct().getCategory()) {
			case CURRENT:
				Calendar calendar = Calendar.getInstance();
				String dateStr = formatDate(getMinDate(calendar.getTime(), getExpiredDate()));
				for(FinancingIncomeRule rule:getFinancingIncomeRules()){
					if (dateStr.compareTo(rule.getDueDate()) <= 0) {
						return rule;
					}
				}
				break;
			default:
				break;
			}
		}
		return null;
	}
	
	public boolean isBeforeRedemptionDate() {
		FinancingIncomeRule rule = getFinancingIncomeRule();
		if (rule != null) {
			return formatDate(Calendar.getInstance()).compareTo(
					rule.getRedemptionStartTime()) < 0;
		}
		return false;
	}
	
	public boolean isAfterRedemptionDate() {
		FinancingIncomeRule rule = getFinancingIncomeRule();
		if (rule != null) {
			return formatDate(Calendar.getInstance()).compareTo(
					rule.getRedemptionEndTime()) > 0;
		}
		return false;
	}
    
	/**
	 * 是否可赎回
	 * 
	 * @return
	 */
	public boolean isRedemption() {
		FinancingIncomeRule rule = getFinancingIncomeRule();
		if (rule != null && !isRedeemed() && !rule.isLast()) {
			String now = formatDate(Calendar.getInstance());
			return now.compareTo(rule.getRedemptionStartTime()) >= 0
					&& now.compareTo(rule.getRedemptionEndTime()) <= 0;
		}
		return false;
	}
	
    /**
     * 是否已赎回
     * @return
     */
    public boolean isRedeemed() {
    	RedemptionRequestMapper redemptionRequestMapper = CommonServiceImpl.applicationContext.getBean(RedemptionRequestMapper.class);
    	RedemptionRequestExample example = new RedemptionRequestExample();
		example.appendCriterion("financing_id=", getId());
		return redemptionRequestMapper.countByExample(example)>0;
    }
    
    /**
     * 获取投资最终收益
     * @return	投资最终收益
     */
    public BigDecimal getInvestmentIncome() {
    	BigDecimal income = new BigDecimal(
    			this.getAmount().doubleValue()
    			* (this.getInterestRate().doubleValue())
    			/ 360 * this.getTerm()).setScale(2, RoundingMode.UP);
    	return income;
    }

	public String getTrack() {
		return track;
	}

	public void setTrack(String track) {
		this.track = track;
	}

	public Integer getMinTerm() {
		return minTerm;
	}

	public void setMinTerm(Integer minTerm) {
		this.minTerm = minTerm;
	}

    @JsonView({DetailView.class})
	public Integer getOccupiedDays() {
		
		return (occupiedDays == null)?DateTimeUtil.getDaysBetween(this.getValueDate(), new Date()).intValue():occupiedDays;
		
	}

	public void setOccupiedDays(Integer occupiedDays) {
		this.occupiedDays = occupiedDays;
	}
	
}
